<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>14.private私有属性使用</title>
</head>

<body>

</body>
<script>
  //设置对象的私有属性有多种方式，包括后面章节介绍的模块封装。
  /*
  1. public 指不受保护的属性，在类的内部与外部都可以访问到 
  2. protected是受保护的属性修释，不允许外部直接操作，但可以继承后在类内部访问，有以下几种方式定义
    1. 将属性定义为以 _ 开始，来告诉使用者这是一个私有属性，请不要在外部使用
       - 外部修改私有属性时可以使用访问器 setter 操作
       - 但这只是提示，就像吸烟时烟盒上的吸烟有害健康，但还是可以抽的
    2. 使用 Symbol定义私有访问属性，即在外部通过查看对象结构无法获取的属性,类本身和子类可以访问
    3. 利用WeakMap类型特性定义私有属性   
  3. private 指私有属性，只在当前类可以访问到，并且不允许继承使用
  */
  /* - 为属性或方法名前加 # 为声明为私有属性
     - 私有属性只能在声明的类中使用
 
 下面声明私有属性 #host 与私有方法 check 用于检测用户名 */


  class Common {
    // public
    #url = "houdunren.com";
    constructor(name) {
      this.name = name;
      this.#check(name);
    }

    set url (url) {
      if (!/^https?:/i.test(url)) {
        throw new Error("非常网址");
      }
      this.#url = url;
    }
    get url () {
      return this.#url;
    }
    // 私有方法不能直接用# 命名，需要用私有属性赋值才能做到
    #check = () => {
      if (this.name.length < 5) {
        throw new Error('用户名长度不得小于5位');
      }
      return true;
    }
  }
  class User extends Common {
    constructor(name) {
      super(name);
      //this.#check();  //不能使用父类的私有方法Uncaught SyntaxError: Private field '#check' must be declared in an enclosing class (at
    }

  }
  let hd = new User("后盾人112233");
  // 直接修改私有属性回报错 Uncaught SyntaxError: Private field '#url' must be declared in an enclosing class (at 14.private私有属性使用.html:53:5)
  hd.url = "https://houdurnen.com2"
  // 可以使用访问器获取，修改 私有属性
  console.log(hd.name, hd.url);

</script>

</html>